package com.yonyou.ucf.mdd.ext.bill.rule.util;

import com.alibaba.fastjson.JSONObject;
import com.yonyou.iuap.bd.common.exception.BaseDocException;
import com.yonyou.iuap.data.entity.dto.FuncOrg;
import com.yonyou.iuap.data.entity.dto.OrgUnit;
import com.yonyou.iuap.data.service.itf.FuncOrgDataQryService;
import com.yonyou.iuap.international.MultiLangText;
import com.yonyou.iuap.ml.vo.LanguageVO;
import com.yonyou.permission.mdd.utils.MddAuthPermissionUtils;
import com.yonyou.uap.billcode.service.IBillCodeComponentService;
import com.yonyou.ucf.mdd.api.interfaces.rpc.IComOperateApi;
import com.yonyou.ucf.mdd.common.constant.MddConstants;
import com.yonyou.ucf.mdd.common.exceptions.error.MddOrmErrorException;
import com.yonyou.ucf.mdd.common.exceptions.message.MddBillcodeMsgException;
import com.yonyou.ucf.mdd.common.exceptions.message.MddZeroResultMsgException;
import com.yonyou.ucf.mdd.common.exceptions.message.MsgExceptionCode;
import com.yonyou.ucf.mdd.common.model.rule.RuleExecuteResult;
import com.yonyou.ucf.mdd.common.model.uimeta.filter.vo.FilterVO;
import com.yonyou.ucf.mdd.common.model.uimeta.ui.View;
import com.yonyou.ucf.mdd.core.utils.ConditionUtil;
import com.yonyou.ucf.mdd.core.utils.IMetaUtils;
import com.yonyou.ucf.mdd.ext.base.itf.*;
import com.yonyou.ucf.mdd.ext.base.user.User;
import com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto;
import com.yonyou.ucf.mdd.ext.bill.meta.model.TplQueryParam;
import com.yonyou.ucf.mdd.ext.bill.meta.service.MddBillTplQueryService;
import com.yonyou.ucf.mdd.ext.bill.service.BillMasterOrgService;
import com.yonyou.ucf.mdd.ext.consts.Constants;
import com.yonyou.ucf.mdd.ext.core.AppContext;
import com.yonyou.ucf.mdd.ext.dao.meta.MetaDaoHelper;
import com.yonyou.ucf.mdd.ext.dao.meta.UiMetaDaoHelper;
import com.yonyou.ucf.mdd.ext.dao.meta.crud.MetaDaoSupport;
import com.yonyou.ucf.mdd.ext.dao.meta.crud.MetaDaoSupportUtil;
import com.yonyou.ucf.mdd.ext.dao.sql.SqlHelper;
import com.yonyou.ucf.mdd.ext.dubbo.DubboReference;
import com.yonyou.ucf.mdd.ext.dubbo.DubboReferenceUtils;
import com.yonyou.ucf.mdd.ext.meta.MetaAttributeUtils;
import com.yonyou.ucf.mdd.ext.model.BillContext;
import com.yonyou.ucf.mdd.ext.model.CodeGrade;
import com.yonyou.ucf.mdd.ext.model.LoginUser;
import com.yonyou.ucf.mdd.ext.option.util.OptionUtils;
import com.yonyou.ucf.mdd.ext.util.*;
import com.yonyou.ucf.mdd.ext.util.json.GsonHelper;
import com.yonyou.ucf.mdd.ext.util.localcache.AbstractSystemCacheUtil;
import com.yonyou.ucf.mdd.ext.util.localcache.OptionValueRpcCacheUtil;
import com.yonyou.ucf.mdd.ext.util.rpc.RpcBaseService;
import com.yonyou.ucf.mdd.ext.util.union.MdfMapKeyUtil;
import com.yonyou.ucf.mdd.ext.voucher.base.Vouch;
import com.yonyou.ucf.mdd.ext.voucher.enums.Status;
import com.yonyou.ucf.mdd.isv.service.ISVServiceFactory;
import com.yonyoucloud.uretail.api.IBillQueryService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.imeta.biz.base.BizContext;
import org.imeta.biz.base.MetaUtils;
import org.imeta.biz.base.Objectlizer;
import org.imeta.biz.walker.ChainWalker;
import org.imeta.biz.walker.EntityWalker;
import org.imeta.core.base.ConditionOperator;
import org.imeta.core.lang.BooleanUtils;
import org.imeta.core.model.*;
import org.imeta.orm.base.*;
import org.imeta.orm.schema.QueryConditionGroup;
import org.imeta.orm.schema.QuerySchema;
import org.imeta.orm.schema.SimpleCondition;
import org.imeta.spring.base.MetaBeanFactory;
import org.imeta.spring.base.SqlBuilderType;
import org.imeta.spring.support.db.UniqueCheckWalker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class BillInfoUtils {
    private static final String TREE_TABLE_ID_COLUMN_NAME = "idColumn";

    private static final Logger logger = LoggerFactory.getLogger(com.yonyou.ucf.mdd.ext.bill.rule.util.BillInfoUtils.class);

    private static final Pattern WHERESQL_PATTERN = Pattern.compile("where(.+)");

    private static FuncOrgDataQryService funcOrgDataQryService;

    private static FuncOrgDataQryService getFuncOrgDataQryService() {
        ISVServiceFactory isvBeanService = AppContext.getBean(ISVServiceFactory.class);
        FuncOrgDataQryService service = isvBeanService.getFuncOrgDataQryService("orgcenter");
        BillInfoUtils.funcOrgDataQryService = service;
        //后面替换成调用 getUserMasterOrgPermWithOutGroup 方法,考虑效率问题，暂停替换
        return funcOrgDataQryService;
    }

    public static void setTenant(BillContext billContext, BizObject bill) throws Exception {
        List<BizObject> bills = new ArrayList<>(1);
        bills.add(bill);
        AppContext.setPartitionData(billContext.getFullname(), bills);
        /*
         * //TenantId if (bill instanceof ITenant) { ITenant tenant = (ITenant) bill; if
         * (tenant.getTenant() == null) { Object tenantId = AppContext.getTenantId();
         * tenant.setTenant(tenantId); } } if (bill instanceof ICust) { LoginUser
         * user=AppContext.getCurrentUser(); if(null!=user){ Long customerId =
         * user.getCustomer(); if(null!=customerId){ bill.set("cust", customerId); } } }
         */
    }

    private static boolean isBlank(Map map, Object key) {
        if (!map.containsKey(key)) {
            return true;
        }
        if (map.get(key) == null) {
            return true;
        }
        if (map.get(key) instanceof String) {
            if (StringUtils.isEmpty((String) map.get(key))) {
                return true;
            }
        }
        return false;
    }

    public static void setAddAuditInfo(BizObject bill) {
        if (bill instanceof IAuditInfo) {
            IAuditInfo obj = (IAuditInfo) bill;
            User user = AppContext.getCurrentUser();
            if (null != user) {
                if (!Toolkit.isEmpty(user.getName())) {
                    if (StringUtils.isEmpty(obj.getCreator())) {
                        obj.setCreator(user.getName());
                    }
                }
                if (isBlank(bill, "id") || bill.getEntityStatus() == EntityStatus.Insert) {
                    if (!bill.containsKey("creatorId")) {
                        bill.set("creatorId", user.getId());
                    }
                    if (!bill.containsKey("creator")) {
                        bill.set("creator", user.getName());
                    }
                }
                if (bill.getEntityStatus() == EntityStatus.Update) {
                    bill.set("modifierId", user.getId());
                    bill.set("modifier", user.getName());
                }
            }
            if (isBlank(bill, "id") || bill.getEntityStatus() == EntityStatus.Insert) {
                obj.setCreateTime(DateKit.getNowDate());// new Date());
                obj.setCreateDate(DateKit.getNowDate());// new Date());
            }
            if (bill.getEntityStatus() == EntityStatus.Update) {
                obj.setModifyTime(DateKit.getNowDate());
                obj.setModifyDate(DateKit.getNowDate());
            }
        }
        if (bill instanceof IStopping) {
            IStopping obj = (IStopping) bill;
            if (BooleanUtils.b(obj.getStopstatus()) && null == obj.getStoptime()) {
                obj.setStoptime(DateKit.getNowDate());// new Date());
            }
        }
    }

    /**
     * @return void
     * @Description
     * @Param [bill]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE setAddVouchDateInfo(BizObject bill, Entity entity)
     **/
    @Deprecated
    public static void setAddVouchDateInfo(BizObject bill) {
        setAddVouchDateInfo(bill, (Entity) null);
    }

    /**
     * @return void
     * @Description
     * @Param [bill]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE setAddVouchDateInfo(BizObject bill, Entity entity)
     **/
    @Deprecated
    public static void setAddVouchDateInfo(BizObject bill, String fullname) {
        Entity entity = IMetaUtils.entity(fullname);
        setAddVouchDateInfo(bill, entity);
    }

    public static void setAddVouchDateInfo(BizObject bill, Entity entity) {
        if (isVouchClass(entity, bill)) {
            bill.set("vouchdate", getBusinessDate());
        }
    }

    /**
     * 新增分类档案时，path加本id
     *
     * @param bill
     */
    public static void setPathInfoWhenInsert(BizObject bill) {
        if (bill instanceof ITree) {
            ITree obj = (ITree) bill;
            String path = obj.getPath();
            if (null == path) {
                path = "|" + bill.getId().toString() + "|";
            } else {
                path += bill.getId().toString() + "|";
            }
            obj.setPath(path);

            /*
             * if (null != obj.getParent() && 0 == obj.getParent()) { obj.setParent(null); }
             */
            if (null == obj.getLevel() || 0 == obj.getLevel()) {
                obj.setLevel(1);
            }
            obj.setIsEnd(true);
        }
    }

    public static void setPathInfoWhenUpdate(BizObject bill) {
        if (bill instanceof ITree) {
            ITree obj = (ITree) bill;

            /*
             * if (null != obj.getParent() && 0 == obj.getParent()) { obj.setParent(null); }
             */
            if (null == obj.getLevel() || 0 == obj.getLevel()) {
                obj.setLevel(1);
            }
        }
    }

    public static void setEditAuditInfo(BizObject bill) {
        if (bill instanceof IAuditInfo) {
            IAuditInfo obj = (IAuditInfo) bill;
            User user = AppContext.getCurrentUser();
            if (null != user) {
                if (!Toolkit.isEmpty(user.getName()))
                    obj.setModifier(user.getName());
                bill.set("modifierId", user.getId());
            }
            obj.setModifyTime(DateKit.getNowDate());// new Date());
            obj.setModifyDate(DateKit.getNowDate());// new Date());
        }
        if (bill instanceof IStopping) {
            IStopping obj = (IStopping) bill;
            if (BooleanUtils.b(obj.getStopstatus()) && null == obj.getStoptime()) {
                obj.setStoptime(DateKit.getNowDate());// new Date());
            }
        }

    }

    /**
     * @return
     * @Description 单据状态
     * @Param
     * @Author DaeDalu$
     * @Date
     * @deprecated USE setStatusInfo(Entity entity, BizObject bill, Status status)
     **/
    @Deprecated
    public static void setStatusInfo(BizObject bill, Status status) {
        setStatusInfo(null, bill, status);
    }

    public static void setStatusInfo(Entity entity, BizObject bill, Status status) {
        if (isVouchClass(entity, bill)) {
            bill.set("status", status.getValue());
        }
    }

    public static boolean isVouchClass(Entity entity, BizObject bill) {
        if (bill instanceof Vouch) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(entity, "ucfbase.vouch.Vouch")) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(entity, "voucher.base.Vouch")) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(bill.getEntityName(), "ucfbase.vouch.Vouch")) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(bill.getEntityName(), "voucher.base.Vouch")) {
            return true;
        }
        return false;
    }

   /* private static boolean isVouchClass(BizObject bill) {
        if (bill instanceof Vouch) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(bill.getEntityName(), "ucfbase.vouch.Vouch")) {
            return true;
        } else if (IMetaUtils.isInheritanceFrom(bill.getEntityName(), "voucher.base.Vouch")) {
            return true;
        }
        return false;
    }*/

    public static void setAuditInfo(BizObject bill) throws Exception {
        setAuditInfo(null, bill);
    }

    public static void setAuditInfo(Entity entity, BizObject bill) throws Exception {
        bill.set("_status", EntityStatus.Update);
        bill.set(MddConstants.PARAM_BPM_VERIFYSTATE, Short.valueOf(MddConstants.STR_NUM_TWO));

        User user = AppContext.getCurrentUser();
        if (bill instanceof IApprovalInfo) {
            logger.info("BillInfoUtils.setAuditInfo 通过分支 bill instanceof IApprovalInfo 设置");
            IApprovalInfo obj = (IApprovalInfo) bill;

            if (null != user) {
                if (!Toolkit.isEmpty(user.getName()))
                    obj.setAuditor(user.getName());
                bill.set("auditorId", user.getId());
            }
            obj.setAuditTime(DateKit.getNowDate());// new Date());
            obj.setAuditDate(getBusinessDate());// new Date());
            bill.set("_status", EntityStatus.Update);
        } else if (null != entity && null != user && IMetaUtils.isImplementOf(entity, "base.itf.IApprovalInfo")) {
            logger.info("BillInfoUtils.setAuditInfo 通过分支 isImplementOf( base.itf.IApprovalInfo ) 设置");
            bill.set("auditor", user.getName());
            bill.set("auditorId", user.getId());
            bill.set("auditTime", DateKit.getNowDate());
            bill.set("auditDate", getBusinessDate());
            bill.set("_status", EntityStatus.Update);
        } else if (null != entity && null != user && IMetaUtils.isImplementOf(entity, "ucfbase.ucfbaseItf.IApprovalInfo")) {
            logger.info("BillInfoUtils.setAuditInfo 通过分支 isImplementOf( ucfbase.ucfbaseItf.IApprovalInfo ) 设置");
            bill.set("auditor", user.getId());
            bill.set("auditTime", new Date());
        }
        if (bill instanceof IApprovalFlow || (null != entity && IMetaUtils.isImplementOf(entity, "base.itf.IApprovalFlow"))) {
            bill.set("verifystate", Short.valueOf("2"));
        }
    }

    // 提交信息
    public static void setSubmitInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("verifystate", Short.valueOf("1"));
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 提交不控制信息
    public static void setSubmitNoControlInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("isWfControlled", false);
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 提交撤消
    public static void setUnSubmitInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("verifystate", Short.valueOf("0"));
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 审批不同意
    public static void setDisagreeInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("verifystate", Short.valueOf("3"));
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 审批同意
    public static void setAgreeInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("verifystate", Short.valueOf("2"));
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 审批退回
    public static void setReturnInfo(BizObject bill) throws Exception {
        if (bill instanceof IApprovalFlow) {
            bill.set("returncount", "++1");
            bill.set("_status", EntityStatus.Update);
        }
    }

    // 删除时有后续操作
    public static QueryConditionGroup hasNextWhenDelete(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildAudited(condition, bill);
        buildClosed(condition, bill);
        return condition;
    }

    // 审核时有后续操作
    public static QueryConditionGroup hasNextWhenAudit(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildAudited(condition, bill);
        buildClosed(condition, bill);
        return condition;
    }

    // 作废时有后续操作
    public static QueryConditionGroup hasNextWhenInvalid(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildInvalid(condition, bill);
        return condition;
    }

    // 弃审核时有后续操作
    public static QueryConditionGroup hasNextWhenUnAudit(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildUnAudited(condition, bill);
        buildClosed(condition, bill);
        return condition;
    }

    // 关闭时有后续操作
    public static QueryConditionGroup hasNextWhenClose(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildClosed(condition, bill);
        return condition;
    }

    /**
     * @return org.imeta.orm.schema.QueryConditionGroup
     * @Description
     * @Param [bill]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE hasNextWhenLock(Entity entity, BizObject bill)
     **/
    @Deprecated
    public static QueryConditionGroup hasNextWhenLock(BizObject bill) throws Exception {
        return hasNextWhenLock(null, bill);
    }

    public static QueryConditionGroup hasNextWhenLock(Entity entity, BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildLock(condition, bill);
        return condition;
    }

    public static QueryConditionGroup hasNextWhenUnClose(BizObject bill) throws Exception {
        QueryConditionGroup condition = new QueryConditionGroup(ConditionOperator.and);

        buildUnClosed(condition, bill);
        return condition;
    }

    // 已审核
    public static void buildAudited(QueryConditionGroup condition, BizObject bill) throws Exception {

        if (bill instanceof IApprovalInfo) {
            SimpleCondition item = null;
            item = new SimpleCondition("auditor", ConditionOperator.is_null, null);
            condition.appendCondition(item);
        }
        buildInvalid(condition, bill);

    }

    // 已弃审
    public static void buildUnAudited(QueryConditionGroup condition, BizObject bill) throws Exception {
        if (bill instanceof IApprovalInfo) {
            SimpleCondition item = null;

            item = new SimpleCondition("auditor", ConditionOperator.is_not_null, null);
            condition.appendCondition(item);
        }
        buildInvalid(condition, bill);
        // buildLock(condition, bill);
    }

    // 已关闭
    public static void buildClosed(QueryConditionGroup condition, BizObject bill) throws Exception {

        if (bill instanceof IClosing) {
            SimpleCondition item = null;
            item = new SimpleCondition("closer", ConditionOperator.is_null, null);
            condition.appendCondition(item);
        }
        buildInvalid(condition, bill);
        // buildLock(condition, bill);
    }

    // 已作废
    public static void buildInvalid(QueryConditionGroup condition, BizObject bill) throws Exception {

        if (bill instanceof IInvalid) {
            SimpleCondition item = null;
            item = new SimpleCondition("invalidor", ConditionOperator.is_null, null);
            condition.appendCondition(item);
        }

    }

    /**
     * @return void
     * @Description 已锁定
     * @Param [condition, bill]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE buildLock(Entity entity, QueryConditionGroup condition, BizObject bill)
     **/
    @Deprecated
    public static void buildLock(QueryConditionGroup condition, BizObject bill) throws Exception {
        buildLock(null, condition, bill);
    }

    // 已锁定
    public static void buildLock(Entity entity, QueryConditionGroup condition, BizObject bill) throws Exception {

        if (bill instanceof ILock) {
            SimpleCondition item = null;
            item = new SimpleCondition("locker", ConditionOperator.is_null, null);
            condition.appendCondition(item);
            if (isVouchClass(entity, bill)) {
                SimpleCondition item2 = null;
                item2 = new SimpleCondition("status", ConditionOperator.eq, 0);
                condition.appendCondition(item2);
            }
        }

    }

    public static void buildUnClosed(QueryConditionGroup condition, BizObject bill) throws Exception {

        if (bill instanceof IClosing) {
            SimpleCondition item = null;
            item = new SimpleCondition("closer", ConditionOperator.is_not_null, null);
            condition.appendCondition(item);
        }
        buildInvalid(condition, bill);

    }


    /**
     * 设置主表关闭信息
     *
     * @param bill
     * @param user
     * @throws Exception
     */
    public static void setMainCloseInfo(BizObject bill, User user) {
        if (bill instanceof IClosing) {
            IClosing obj = (IClosing) bill;
            if (null != user) {
                if (!Toolkit.isEmpty(user.getName()))
                    obj.setCloser(user.getName());
                bill.set("closerId", user.getId());
            }
            obj.setCloseTime(DateKit.getNowDate());
            obj.setCloseDate(getBusinessDate());
            bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setCloseInfo(BizObject bill, String fullname) throws Exception {
        if (bill instanceof IClosing) {
            User user = AppContext.getCurrentUser();
            setMainCloseInfo(bill, user);
            Entity subEntity = MetaDaoHelper.getSubEntity(fullname);
            String childAttribute = MetaDaoHelper.getChilrenField(fullname);// bill.get("childAttribute");
            List<BizObject> childBills = bill.get(childAttribute);
            if (childBills != null && childAttribute.length() > 0) {
                for (BizObject childBill : childBills) {
                    if (childBill != null && childBill instanceof ILineClosing) {
                        ILineClosing childObj = (ILineClosing) childBill;
                        if (childObj.getLinecloseTime() != null || childObj.getLinecloser() != null) {
                            continue;
                        }
                        if (null != user) {
                            if (!Toolkit.isEmpty(user.getName()))
                                childObj.setLinecloser(user.getName());
                        }
                        childObj.setLinecloseTime(DateKit.getNowDate());// new Date());
                        if (subEntity.is(BizContext.getMetaRepository().itf("base.itf.ILineDateClosing"))) {
                            childBill.set("linecloseDate", getBusinessDate());
                        }
                        childBill.set("_status", EntityStatus.Update);
                    }
                }
            }
        }
    }

    public static void setLineCloseInfo(BizObject bill, String childAttribute) {
        // if (bill instanceof IClosing) {
        List<BizObject> childBills = bill.get(childAttribute);
        if (childBills != null && childAttribute.length() > 0) {
            for (BizObject childBill : childBills) {// .get(index);
                if (childBill != null && childBill instanceof ILineClosing) {
                    ILineClosing childObj = (ILineClosing) childBill;
                    if (childObj.getLinecloseTime() != null || childObj.getLinecloser() != null) {
                        continue;
                    }
                    User user = AppContext.getCurrentUser();
                    if (null != user) {
                        if (!Toolkit.isEmpty(user.getName()))
                            childObj.setLinecloser(user.getName());
                    }
                    childObj.setLinecloseTime(DateKit.getNowDate());// new Date());
                    childBill.set("_status", EntityStatus.Update);

                    if (childBill != null && childBill instanceof ILineDateClosing) {
                        ILineDateClosing childObj1 = (ILineDateClosing) childBill;
                        childObj1.setLinecloseDate(getBusinessDate());
                    }
                }
            }
        }
        // }
    }

    public static void setUnLineCloseInfo(BizObject bill, String childAttribute) {
        // if (bill instanceof IClosing) {
        List<BizObject> childBills = bill.get(childAttribute);
        if (childBills != null && childAttribute.length() > 0) {
            for (BizObject childBill : childBills) {// .get(index);
                if (childBill != null && childBill instanceof ILineClosing) {
                    ILineClosing childObj = (ILineClosing) childBill;
                    childObj.setLinecloser(null);
                    childObj.setLinecloseTime(null);
                    childBill.set("_status", EntityStatus.Update);
                    if (childBill != null && childBill instanceof ILineDateClosing) {
                        ILineDateClosing childObj1 = (ILineDateClosing) childBill;
                        childObj1.setLinecloseDate(null);
                    }

                    /*
                     * obj.setCloser(null); obj.setCloseTime(null); bill.set("_status",
                     * EntityStatus.Update);
                     */

                }
            }
        }
        if (bill instanceof IClosing) {
            setUnCloseInfo(bill, true);
        }
        // }
    }

    /**
     * @return java.lang.String
     * @Description
     * @Param [bills]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE  refreshCloseField(Entity entity, List<BizObject> bills)
     **/
    @Deprecated
    public static String refreshCloseField(List<BizObject> bills) {
        return refreshCloseField(null, bills);
    }

    public static String refreshCloseField(Entity entity, List<BizObject> bills) {
        if (null != bills && bills.size() > 0) {
            BizObject bill = bills.get(0);
            String fields = null;
            if (bill instanceof IClosing) {
                StringBuffer sb = new StringBuffer();
                sb.append("closer,");
                sb.append("closeTime,");
                sb.append("closeDate,");
                if (isVouchClass(entity, bill)) {
                    sb.append("status,");
                }
                sb.deleteCharAt(sb.length() - 1);
                fields = sb.toString();
            }
            return fields;
        } else {
            return null;
        }
    }

    // 行关闭／打开时整单关闭／打开
    public static void closeBillWhenLineOperate(BizObject bill, String fullname, boolean isOpen) throws Exception {
        if (bill instanceof IClosing) {
            Entity mainEntity = MetaDaoHelper.getEntity(fullname);
            Entity subEntity = MetaDaoHelper.getSubEntity(fullname);
            String foreignKey = MetaDaoHelper.getForeginColumnName(fullname);
            User user = AppContext.getCurrentUser();
            Long id = bill.getId();

            // 更新主表时间戳
            StringBuffer sb = new StringBuffer();
            Property property = mainEntity.syncAttribute();
            String syncColumnName = null;
            if (null != property) {
                syncColumnName = property.columnName();
                sb.append("update " + mainEntity.tableName());

                sb.append(" set " + syncColumnName + "=now()");
                sb.append(" where id=" + id);
                Object syncValue = bill.get(property.name());
                Map<String, Object> para = new HashMap<>();
                if (null != syncValue) {
                    para.put(syncColumnName, syncValue);
                    sb.append(" and " + syncColumnName + "=#{" + syncColumnName + "}");
                }
                MetaDaoSupport dao = new MetaDaoSupport() {
                    @Override
                    public int executeUpdate(Object[] params) throws Exception {
                        String sql = (String) params[0];

                        /*
                         * new NativeSqlSession(AppContext.getSqlSession()) .update(sql);
                         */
                        Map<String, Object> para = (Map<String, Object>) params[1];

                        return new DynamicSqlSession(AppContext.getSqlSession()).update(sql, para);
                    }
                };
                Object[] params = {sb.toString(), para};
                int result = dao.executeUpdate(params);
                if (0 == result && null != syncValue) {
                    throw new MddZeroResultMsgException(MsgExceptionCode.BILL_CHANGED_PLEASE_REFRESH);
                }
            }
            sb = new StringBuffer();
            sb.append("update " + mainEntity.tableName());

            if (isOpen) {
                sb.append(" set " + mainEntity.getAttribute("closer").columnName() + "=null,");
                sb.append(mainEntity.getAttribute("closeTime").columnName() + "=null,");
                sb.append(mainEntity.getAttribute("closeDate").columnName() + "=null");
            } else {
                sb.append(" set " + mainEntity.getAttribute("closer").columnName() + "='" + user.getName() + "',");
                sb.append(mainEntity.getAttribute("closeTime").columnName() + "='" + DateKit.getStringDate() + "',");
                sb.append(mainEntity.getAttribute("closeDate").columnName() + "='" + DateKit.dateToStr(getBusinessDate()) + "'");
            }
            if (isVouchClass(mainEntity, bill)) {
                if (isOpen) {
                    // sb.append(",status="+Status.confirmed.getValue());
                } else {
                    sb.append(",status=" + Status.closed.getValue());
                }
            }
            sb.append(" where id=" + id);

            if (isOpen) {
                sb.append(" and not exists(select id from " + subEntity.tableName());

                sb.append(" where linecloser is not null and " + foreignKey + "=" + id + ")");
            } else {
                sb.append(" and not exists(select id from " + subEntity.tableName());

                sb.append(" where linecloser is null and " + foreignKey + "=" + id + ")");
            }
            sb.append(";");

            if (isOpen) {
                sb.append("update " + mainEntity.tableName()
                        + " a inner join vouch_closestatus b on a.id=b.bill_id and a." + mainEntity.getAttribute(AppContext.getTenantPartitionField()).columnName() + "=b.tenant_id and b.tablename='"
                        + mainEntity.tableName() + "'");
                sb.append(" set a.status=b.status where a.id=" + id + " and a." + mainEntity.getAttribute("closer").columnName() + " is null;");
            } else {
                sb.append("replace into vouch_closestatus(`tablename`,bill_id,tenant_id,`status`)");

                sb.append(" select '" + mainEntity.tableName() + "',id," + mainEntity.getAttribute(AppContext.getTenantPartitionField()).columnName() + "," + bill.get("status")
                        + " as status from " + mainEntity.tableName() + " where id=" + bill.getId()
                        + " and " + mainEntity.getAttribute("closer").columnName() + " is not null;");
            }

            MetaDaoSupport dao = new MetaDaoSupport() {
                @Override
                public int executeUpdate(Object[] params) throws Exception {
                    String sql = (String) params[0];
                    /*
                     * new NativeSqlSession(AppContext.getSqlSession()) .update(sql);
                     */
                    return new DynamicSqlSession(AppContext.getSqlSession()).update(sql, null);
                }
            };
            Object[] params = {sb.toString(), id};
            dao.executeUpdate(params);
        }
    }

    public static void linecloseBillWhenClose(BizObject bill, String fullname, List<Object> childLists, boolean isOpen) throws Exception {
        if (bill instanceof IClosing) {
            Entity subEntity = MetaDaoHelper.getSubEntity(fullname);
            if (!subEntity.is(BizContext.getMetaRepository().itf("base.itf.ILineClosing")))
                return;
            String foreignKey = MetaDaoHelper.getForeginColumnName(fullname);
            User user = AppContext.getCurrentUser();
            Long id = bill.getId();
            StringBuffer sb = new StringBuffer();
            sb.append("update " + subEntity.tableName());
            if (isOpen) {
                sb.append(" set linecloser=null,");
                sb.append(" lineclose_time=null");
            } else {
                sb.append(" set linecloser='" + user.getName() + "',");
                sb.append(" lineclose_time='" + DateKit.getStringDate() + "'");
            }

            if (subEntity.is(BizContext.getMetaRepository().itf("base.itf.ILineDateClosing"))) {
                if (isOpen) {
                    sb.append(",lineclose_date=null");
                } else {
                    sb.append(",lineclose_date='" + DateKit.dateToStr(getBusinessDate()) + "'");
                }
            }

            sb.append(" where " + foreignKey + "=" + id);
            if (CollectionUtils.isNotEmpty(childLists)) {
                String childPrimaryColumnName = subEntity.keyAttribute().columnName();
                String ids = StringUtils.join(childLists, ",");
                sb.append(" and " + childPrimaryColumnName + " in (" + ids + ")");
            }
            if (isOpen) {
                sb.append(" and  linecloser is not null ");
            } else {
                sb.append(" and  linecloser is  null ");
            }
            sb.append(";");
            MetaDaoSupport dao = new MetaDaoSupport() {
                @Override
                public int executeUpdate(Object[] params) throws Exception {
                    String sql = (String) params[0];
                    return new DynamicSqlSession(AppContext.getSqlSession()).update(sql, null);
                }
            };
            Object[] params = {sb.toString(), id};
            dao.executeUpdate(params);
        }
    }

    // 整单关闭／打开时 行关闭／打开
    public static void linecloseBillWhenClose(BizObject bill, String fullname, boolean isOpen) throws Exception {
        linecloseBillWhenClose(bill, fullname, null, isOpen);
    }

    // 新增时 更新上级非末级标记
    public static void updateUpEndWhenInsert(BizObject bill, String fullname) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            ITree obj = (ITree) bill;
            String path = obj.getPath();
            if (null == path) {
                return;
            } else {
                int index = path.lastIndexOf("|", path.length() - 2);
                if (index > -1) {
                    path = path.substring(0, index + 1);
                } else {
                    return;
                }

            }
            Entity entity = MetaDaoHelper.getEntity(fullname);

            StringBuffer sb = new StringBuffer();
            sb.append("update " + entity.tableName());
            sb.append(" set isend=0");

            sb.append(" where path=#{path}");
            Map<String, Object> para = new HashMap<>();
            para.put("path", path);
            MetaDaoSupport dao = new MetaDaoSupport() {
                @Override
                public int executeUpdate(Object[] params) throws Exception {
                    String sql = (String) params[0];
                    // String path = (String) params[1];
                    Map<String, Object> para = (Map<String, Object>) params[1];
                    /*
                     * return new NativeSqlSession(AppContext.getSqlSession()).update( sql, path);
                     */
                    return new DynamicSqlSession(AppContext.getSqlSession()).update(sql, para);

                }
            };
            Object[] params = {sb.toString(), para};
            dao.executeUpdate(params);
        }
    }

    /**
     * @return void
     * @Description 获取树行数据查询的分词条件
     * @Param []
     * @Author DaeDalu$
     * @Date
     **/
    public static String getQueryWhere4UpdateTree(String fullname, BillContext billContext) throws Exception {
        Entity entity = MetaDaoHelper.getEntity(fullname);
        return getQueryWhere4UpdateTree(entity, billContext);
    }

    public static String getQueryWhere4UpdateTree(Entity entity, BillContext billContext) throws Exception {
        if (!BillContextUtils.isTree(entity)) {
            logger.info("未实现 tree 元数据接口; 不处理 getQueryWhere4UpdateTree");
            return null;
        }

        QuerySchema querySchema = QuerySchema.create().addSelect("1 as totalCount");
        MetaDaoSupportUtil.setPartitionToQuerySchema(entity, querySchema, billContext, false);

        SqlBuilder<QuerySchema> builder = MetaBeanFactory.getSqlBuilder(SqlBuilderType.Query);
        SqlStruct sqlStruct = builder.build(entity, querySchema);

        String sql = sqlStruct.rawSql().toString();
        logger.info("getQueryWhere4UpdateTree rawSql: " + sql);
        // Pattern pattern = Pattern.compile("where([\\s\\S]+)");
        Matcher matcher = WHERESQL_PATTERN.matcher(sql);
        String whereSql = null;
        while (matcher.find()) {
            whereSql = matcher.group(1);
        }
        if (whereSql == null) {
            return null;
        }
        logger.info("getQueryWhere4UpdateTree whereSql: " + whereSql);
        whereSql = whereSql.replaceAll("T0\\.", "a.");
        logger.info("getQueryWhere4UpdateTree whereSql replaced: " + whereSql);

        return whereSql;
    }

    /**
     * @return void
     * @Description 更新树
     * @Param [bill, fullname, tenantId, oldParent, oldPath]
     * @Author DaeDalu$
     * @Date
     * @deprecated use updateTree(BizObject bill, String fullname, Object tenantId, Object oldParent, String oldPath, boolean isDeptTree, String updateTreeWhere)
     **/
    @Deprecated
    public static void updateTree(BizObject bill, String fullname, Object tenantId, Object oldParent, String oldPath)
            throws Exception {
        updateTree(bill, fullname, tenantId, oldParent, oldPath, false);
    }

    /**
     * @return void
     * @Description 更新树
     * @Param [bill, fullname, tenantId, oldParent, oldPath]
     * @Author DaeDalu$
     * @Date
     * @deprecated use updateTree(BizObject bill, String fullname, Object tenantId, Object oldParent, String oldPath, boolean isDeptTree, String updateTreeWhere)
     **/
    @Deprecated
    public static void updateTree(BizObject bill, String fullname, Object tenantId, Object oldParent, String oldPath,
                                  boolean isDeptTree) throws Exception {
        updateTree(bill, fullname, tenantId, oldParent, oldPath, isDeptTree, null);
    }

    // 更新树 TODO 处理逻辑删除
    public static void updateTree(BizObject bill, String fullname, Object tenantId, Object oldParent, String oldPath,
                                  boolean isDeptTree, String partitionWhereCondition) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            partitionWhereCondition = StringUtils.isBlank(partitionWhereCondition) ? "1=1" : partitionWhereCondition;//设置非空条件
            Object id = bill.getId();
            Entity entity = MetaDaoHelper.getEntity(fullname);
            Map<String, Object> params = new HashMap<>();
            params.put("tableName", entity.tableName());
            params.put("partitionCondition", partitionWhereCondition);
            String idColumnName = "id";
            try {
                Property keyAttribute = entity.keyAttribute();
                if (null != keyAttribute) {
                    idColumnName = keyAttribute.columnName();
                }
            } catch (Exception exception) {
                logger.error(exception.getMessage(), exception);
            }
            params.put("id", id);
            params.put(TREE_TABLE_ID_COLUMN_NAME, idColumnName);
            Property pathProperty = entity.getAttribute("path");
            String delimiter = "|";
            if (null != pathProperty && null != pathProperty.get("delimiter")) {
                delimiter = pathProperty.get("delimiter");
            }
            Property levelProperty = entity.getAttribute("level");
            Property parentProperty = entity.getAttribute("parent");
            Property isEndProperty = entity.getAttribute("isEnd");

            params.put("delimiter", delimiter);
            params.put("path", pathProperty.get("columnName"));
            params.put("level", levelProperty.get("columnName"));
            params.put("parent", parentProperty.get("columnName"));
            params.put("isEnd", isEndProperty.get("columnName"));

            Object parent = bill.get("parent");
            List<String> parents = null;
            if (null == parent) {
                parents = new ArrayList<>();
            } else {
                parents = new ArrayList(Arrays.asList(new String[]{parent.toString()}));
            }
            if (null != oldParent) {
                if (!parents.contains(oldParent.toString())) {
                    parents.add(oldParent.toString());
                }
            }
            if (isDeptTree)
                params.put("isDeptTree", true);
            params.put("oldpath", oldPath);

            Map<String, Object> newPath = SqlHelper.selectFirst(
                    "com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.selectNewPath" + (isDeptTree ? "Dept" : ""), params);
            if (null != newPath && newPath.size() > 0) {
                Object nodePathObj = newPath.get("newpath");
                if (StringUtils.isNotBlank(oldPath) && null != nodePathObj && oldPath.equals(nodePathObj.toString())) {
                    params.remove(oldPath);
                }
                params.putAll(newPath);
            }
            if (null != parents && parents.size() > 0) {
                String childWhere = " where " + parentProperty.get("columnName") + " in ("
                        + String.format("%s%s%s", "'", StringUtils.join(parents, "','"), "'") + ")";
                String parentWhere = " where a." + idColumnName + " in ("
                        + String.format("%s%s%s", "'", StringUtils.join(parents, "','"), "'") + ")";
                childWhere = childWhere + " and " + partitionWhereCondition.replaceAll("a\\.", "");
                parentWhere = parentWhere + " and " + partitionWhereCondition;
                params.put("parentWhere", parentWhere);
                params.put("childWhere", childWhere);
            }

            logger.info("BillRuleDao.updateTree params: " + GsonHelper.ToJSon(params));
            // 为防止并发数据库死锁加锁执行,暂时采用synchronized锁
            SqlHelper.update("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.updateTree", params);
            if (StringUtils.isNotBlank(oldPath)) {
                updateOldPath(params);
            }
            if (params.get("parentWhere") != null && !"".equals(params.get("parentWhere").toString().trim())) {
                updateTreeEndPart(params);
            }
        }
    }

    public static void updateTreeEndPart(Map<String, Object> params) throws Exception {
        List<Map<String, Object>> idList = SqlHelper.selectList("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.selectTreeTreeEndPartIdList", params);
        if (CollectionUtils.isEmpty(idList)) {
            return;
        }
        for (Map<String, Object> m : idList) {
            m.put("tableName", params.get("tableName"));
            m.put("isEnd", params.get("isEnd"));
            m.put("isEndValue", m.get("childId") == null ? 1 : 0);
            m.put(TREE_TABLE_ID_COLUMN_NAME, params.get(TREE_TABLE_ID_COLUMN_NAME));
        }
        SqlHelper.update("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.updateTreeTreeEndPartByIdList", idList);
    }

    public static void updateOldPath(Map<String, Object> params) throws Exception {
        List<Object> idList = SqlHelper.selectList("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.selectTreeIdList", params);
        if (CollectionUtils.isEmpty(idList)) {
            return;
        }
        params.put("oldTreeIds", idList);
        SqlHelper.update("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.updateOldPath", params);
    }

    public static Map<String, Object> getOldParent(String fullname, BizObject bill) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            if (bill.containsKey("parent")) {// 说明修改了上级
                return getTree(fullname, bill);
            }
        }
        return null;
    }

    public static Map<String, Object> getTree(String fullname, BizObject bill) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            List<Map<String, Object>> list = MetaDaoHelper.queryById(fullname, "parent,path", bill.getId());
            if (list != null && list.size() > 0 && null != list.get(0)) {
                Map<String, Object> line = list.get(0);
                return line;
            }
        }
        return null;
    }

    public static Object getParent(String fullname, BizObject bill) throws Exception {
        Map<String, Object> tree = getTree(fullname, bill);
        if (null != tree && tree.size() > 0) {
            return tree.get("parent");
        }
        return null;
    }

    // 删除时 更新上级非末级标记
    public static void updateUpEndWhenDelete(BizObject bill, String fullname, Object parent) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            Entity entity = MetaDaoHelper.getEntity(fullname);
            Map<String, Object> params = new HashMap<>();
            params.put("tableName", entity.tableName());
            Property isEndProperty = entity.getAttribute("isEnd");
            Property parentProperty = entity.getAttribute("parent");

            String idColumnName = "id";
            try {
                Property keyAttribute = entity.keyAttribute();
                if (null != keyAttribute) {
                    idColumnName = keyAttribute.columnName();
                }
            } catch (Exception exception) {
                logger.error(exception.getMessage(), exception);
            }
            params.put(TREE_TABLE_ID_COLUMN_NAME, idColumnName);

            params.put("parent", parentProperty.get("columnName"));
            params.put("isEnd", isEndProperty.get("columnName"));
            params.put(TREE_TABLE_ID_COLUMN_NAME, idColumnName);

            if (null != parent) {
                String childWhere = " where " + parentProperty.get("columnName") + " ='" + parent + "'";
                String parentWhere = " where a." + idColumnName + "='" + parent + "'";
                params.put("parentWhere", parentWhere);
                params.put("childWhere", childWhere);
                params.put("id", parent);

                //处理逻辑删除的
                boolean isDeletable = ConditionUtil.isDeletable(entity);
                if (isDeletable) {
                    logger.warn("BillInfoUtils updateUpEndWhenDelete 元数据继承逻辑删除接口，开始处理增加逻辑删除的条件");
                    String itfFullname = AppContext.getEnvConfig(MddConstants.CONFIG_LOGIC_DEL_ITF, MddConstants.LOGIC_DELETE_ITF_FULLNAME);
                    Interface itf = BizContext.getMetaRepository().itf(itfFullname);
                    String delFieldName = ConditionUtil.getLogicDelName(itf);
                    params.put("logicDelField", delFieldName);
                    params.put("logicDelVal", ConditionUtil.DELETED);
                }

                List<Map<String, Object>> childList = SqlHelper.selectList("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.selectAllChild", params);
                Map<String, Object> parentData = SqlHelper.selectOne("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.selectTreeDataById", params);
                Boolean isEnd = null;
                boolean updateFlag = false;
                if (MapUtils.isNotEmpty(parentData)) {
                    Object endValue = parentData.get(isEndProperty.get("columnName"));
                    if (null != endValue) {
                        try {
                            isEnd = BooleanUtils.b(endValue.toString());
                        } catch (NumberFormatException e) {
                            logger.warn("BillInfoUtils::updateUpEndWhenDelete::isEnd属性类型转换异常");
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(childList)) {
                    String finalIdColumnName = idColumnName;
                    List<Map<String, Object>> filterdList = childList.stream().filter(child -> null != child.get(finalIdColumnName)).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(filterdList)) {
                        if (null == isEnd || isEnd) {
                            params.put("endValue", 0);
                            updateFlag = true;
                        }
                    } else {
                        if (null == isEnd || !isEnd) {
                            params.put("endValue", 1);
                            updateFlag = true;
                        }
                    }
                } else {
                    if (null == isEnd || !isEnd) {
                        params.put("endValue", 1);
                        updateFlag = true;
                    }
                }
                if (updateFlag) {
                    SqlHelper.update("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.updateTreeEndById", params);
                }
                // SqlHelper.update("com.yonyou.ucf.mdd.ext.bill.dao.BillRuleDao.updateTreeEnd", params);
            }
        }
    }

    public static void setUnAuditInfo(BizObject bill) {
        setUnAuditInfo(bill, true);
    }

    public static void setUnAuditInfo(BizObject bill, boolean isUpdate) {
        bill.set(MddConstants.PARAM_BPM_VERIFYSTATE, Short.valueOf(MddConstants.STR_NUM_ZERO)); // 非营销框架为实现营销接口按照这个设置状态
        if (isUpdate)
            bill.set("_status", EntityStatus.Update);

        if (bill instanceof IApprovalInfo) {
            IApprovalInfo obj = (IApprovalInfo) bill;
            obj.setAuditor(null);
            bill.set("auditorId", null);
            obj.setAuditTime(null);
            obj.setAuditDate(null);
        }
        if (bill instanceof IApprovalFlow) {
            if (BooleanUtils.b(bill.get("isWfControlled"))) {
                bill.set("verifystate", Short.valueOf("1"));
            } else {
                bill.set("verifystate", Short.valueOf("0"));
            }
        }
    }

    public static void clearApprovalFlowInfo(BizObject bill, boolean isUpdate) {
        if (bill instanceof IApprovalFlow) {
            IApprovalFlow obj = (IApprovalFlow) bill;
            obj.setIsWfControlled(false);
            ;
            obj.setVerifystate((short) 0);
            obj.setReturncount((short) 0);
            if (isUpdate)
                bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setUnCloseInfo(BizObject bill, String fullname) throws Exception {
        setUnCloseInfo(bill, true);

        String childAttribute = MetaDaoHelper.getChilrenField(fullname);// bill.get("childAttribute");
        List<BizObject> childBills = bill.get(childAttribute);
        Entity subEntity = MetaDaoHelper.getSubEntity(fullname);

        if (childBills != null && childAttribute.length() > 0) {
            for (BizObject childBill : childBills) {
                if (childBill != null && childBill instanceof ILineClosing) {
                    ILineClosing childObj = (ILineClosing) childBill;
                    if (childObj.getLinecloseTime() == null || childObj.getLinecloser() == null) {
                        continue;
                    }
                    childObj.setLinecloser(null);
                    childObj.setLinecloseTime(null);
                    if (subEntity.is(BizContext.getMetaRepository().itf("base.itf.ILineDateClosing"))) {
                        childBill.set("linecloseDate", null);
                    }
                    childBill.set("_status", EntityStatus.Update);
                }
            }
        }
    }

    public static void setUnCloseInfo(BizObject bill, boolean isUpdate) {
        if (bill instanceof IClosing) {
            IClosing obj = (IClosing) bill;
            obj.setCloser(null);
            bill.set("closerId", null);
            obj.setCloseTime(null);
            obj.setCloseDate(null);
            if (isUpdate)
                bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setUnLineCloseInfo(BizObject bill, int index) {
        if (bill instanceof ILineClosing) {
            ILineClosing obj = (ILineClosing) bill;
            obj.setLinecloser(null);
            obj.setLinecloseTime(null);
        }
    }

    // 刷新时间戳(以及其它字段)
    @SuppressWarnings("rawtypes")
    public static void refreshTs(String fullname, BizObject bill, String refreshField, Object tenantId)
            throws Exception {
        String pubts = null;
//    	Property attribute=MetaUtils.findAttribute(fullname, "pubts");
//    	if(null!=attribute){
//    		pubts=attribute.name();
//    	}
        Entity entity = BizContext.getMetaRepository().entity(fullname);
        if (entity != null && entity.syncAttribute() != null) {
            pubts = entity.syncAttribute().name();
        }
        String refreshField2 = (null == refreshField) ? "" : refreshField;
        if (pubts != null) {
            if (refreshField2.length() > 0) {
                refreshField2 = pubts + "," + refreshField2;
            } else {
                refreshField2 = pubts;
            }
        }
        List<Map<String, Object>> list = MetaDaoHelper.queryById(fullname, refreshField2, bill.getId());
        if (list != null && list.size() > 0 && null != list.get(0)) {
            Map<String, Object> line = list.get(0);
            Iterator iterator = line.entrySet().iterator();

            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                bill.set(entry.getKey().toString(), entry.getValue());
            }
            if (null != refreshField) {
                String[] arr = refreshField.split(",");
                for (String item : arr) {
                    if (!line.containsKey(item)) { // 如果没有返回数据,表示是null
                        bill.set(item, null);
                    }
                }
            }
        }
    }

    /*// 检查编码规则
    public static void checkCodeGrade(String billnum, String fullname, BizObject bill) throws Exception {
        if (bill instanceof ITree || BillContextUtils.isTree(fullname)) {
            String parent = bill.get("parent");
            CodeGrade codeGrade = CodeGradeUtil.getCodeGrade(billnum);
            if (null != codeGrade) {
                String codingRule = codeGrade.getCodingrule();
                char[] chars = codingRule.toCharArray();

                String code = bill.get("code");
                String parentCode = null;
                Long parentId = null;// obj.getParent();
                if (null != parent) {
                    parentId = Long.parseLong(parent);
                }
                Integer level = 1;// obj.getLevel();
                if (null != parentId && parentId.longValue() != 0) {
                    List<Map<String, Object>> list = MetaDaoHelper.queryById(fullname, "code,level", parentId);
                    if (list != null && list.size() > 0 && null != list.get(0)) {
                        parentCode = (String) list.get(0).get("code");
                        Integer parentLevel = (Integer) list.get(0).get("level");
                        level = parentLevel + 1;
                    }
                } else {
                    parentCode = code;
                }

                // 编码长度
                int codeLen = 0;
                // 父编码长度
                int parentLen = 0;
                for (int i = 0; i < level; i++) {
                    codeLen += Integer.parseInt(String.valueOf(chars[i]));
                    if (i < level - 1) {
                        parentLen += Integer.parseInt(String.valueOf(chars[i]));
                    }
                }
                if (code.length() != codeLen) {
                    //"P_YS_FW-PUB_MDD-BACK_0001065653", "不符合编码规则(长度不符)"
                    throw new MddBillcodeMsgException(MsgExceptionCode.BILLCODE_LENGTH_ERROR);
                }
                if (!code.substring(0, parentLen).equals(parentCode)) {
                    //"P_YS_FW-PUB_MDD-BACK_0001065075", "不符合编码规则(父编码不符)"
                    throw new MddBillcodeMsgException(MsgExceptionCode.BILLCODE_PARENTCODE_ERROR);
                }

            }

        }
    }*/

    public static void setLockInfo(BizObject bill) {
        if (bill instanceof ILock) {
            ILock obj = (ILock) bill;
            User user = AppContext.getCurrentUser();
            if (null != user) {
                if (!Toolkit.isEmpty(user.getName()))
                    obj.setLocker(user.getName());
            }
            obj.setLockTime(DateKit.getNowDate());// new Date());
            obj.setLockDate(getBusinessDate());
            bill.set("status", Short.valueOf("4"));

            bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setStopInfo(BizObject bill) {
        if (bill instanceof IStopping) {
            IStopping obj = (IStopping) bill;
            // User user = AppContext.getCurrentUser();
            obj.setStoptime(DateKit.getNowDate());// new Date());
            obj.setStopstatus(true);
            bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setUnstopInfo(BizObject bill) {
        if (bill instanceof IStopping) {
            IStopping obj = (IStopping) bill;
            // User user = AppContext.getCurrentUser();
            obj.setStoptime(null);
            obj.setStopstatus(false);
            bill.set("_status", EntityStatus.Update);
        }
    }

    /**
     * 记录打印次数
     *
     * @param params （ids,billno）
     * @return
     * @throws Exception
     */
    public static List<Map<String, Object>> setBillPrintInfo(Map<String, Object> params) throws Exception {
        params.put("tenantId", AppContext.getTenantId());
        String fullname = SqlHelper.use("uimeta").selectOne("com.yonyou.ucf.mdd.ext.bill.meta.dao.getMainEntity",
                params);
        Entity entity = MetaBeanFactory.getMetaRepository().entity(fullname);
        String tableName = entity.tableName();
        params.put("tableName", tableName);
        String primaryKey = "id";
        for (Property property : entity.attributes()) {
            if (property.isKey() != null && property.isKey()) {
                primaryKey = property.columnName();
            }
        }
        params.put("primaryKey", primaryKey);
        updatePrintCount(entity, params);
        List<Map<String, Object>> result = SqlHelper
                .selectList("com.yonyou.ucf.mdd.ext.bill.dao.BillMetaRefDao.getBillsByIds", params);
        return result;
    }

    public static void updatePrintCount(Entity entity, Map<String, Object> params) throws Exception {
        Component component = entity.owner();
        String domain = component.domain();
        // 获取并发需改控制字段元数据属性
        Property syncAttribute = entity.syncAttribute();
        if (null != syncAttribute) {
            String syncColumnName = syncAttribute.columnName();
            params.put("syncColumnName", syncColumnName);
        }
        new RpcBaseService(domain) {
            @Override
            protected <T> T executer(Object param, String domain) throws Exception {
                IComOperateApi comOperateApi = DubboReferenceUtils.getDubboService(IComOperateApi.class, domain, null);
                comOperateApi.executeSql("com.yonyou.ucf.mdd.ext.bill.dao.BillMetaRefDao.updatePrintCount", params);
                return null;
            }

            @Override
            protected <T> T fallbackExecuter(Object param, String domain) throws Exception {
                Object billQuery = DubboReference.getInstance().getReference(IBillQueryService.class, domain, null, (Integer)null);
                if (null != billQuery) {
                    IBillQueryService billQueryService = (IBillQueryService) billQuery;
                    billQueryService.executeSql("com.yonyou.ucf.mdd.ext.bill.dao.BillMetaRefDao.updatePrintCount",
                            params);
                }
                return null;
            }
        }.execute();
    }

    public static void setInvalidInfo(BizObject bill) {
        if (bill instanceof IInvalid) {
            IInvalid obj = (IInvalid) bill;
            User user = AppContext.getCurrentUser();
            if (null != user) {
                if (!Toolkit.isEmpty(user.getName()))
                    obj.setInvalidor(user.getName());
            }
            obj.setInvalidTime(DateKit.getNowDate());// new Date());
            bill.set("_status", EntityStatus.Update);
        }
    }

    public static void setUnLockInfo(BizObject bill) {
        setUnLockInfo(bill, true);
    }

    public static void setUnLockInfo(BizObject bill, boolean isUpdate) {
        if (bill instanceof ILock) {
            ILock obj = (ILock) bill;

            obj.setLocker(null);
            obj.setLockTime(null);
            obj.setLockDate(null);
            if (isUpdate)
                bill.set("_status", EntityStatus.Update);
        }
    }

    /**
     * @return void
     * @Description
     * @Param [bill]
     * @Author DaeDalu$
     * @Date
     * @deprecated USE clear(Entity entity, BizObject bill)
     **/
    @Deprecated
    public static void clear(BizObject bill) {
        clear(null, bill);
    }

    // 清除id
    // 清除修改人、审核人、关闭人等
    public static void clear(Entity entity, BizObject bill) {
        if (bill instanceof IAuditInfo) {
            IAuditInfo obj = (IAuditInfo) bill;
            obj.setModifier(null);
            bill.set("modifierId", null);
            obj.setModifyTime(null);
            obj.setModifyDate(null);
        }
        setUnCloseInfo(bill, false);
        setUnLockInfo(bill, false);
        setUnAuditInfo(bill, false);
        clearApprovalFlowInfo(bill, false);
        if (null != bill) {
            bill.setId(null);
            bill.setPubts(null);
        }
        setStatusInfo(entity, bill, Status.newopen);
    }

    public static void clone(Class<?> oldClass, Object oldObj, Object newObj) {
        Method[] methods = oldClass.getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            if (methodName.startsWith("set")) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                try {
                    Method methodSet = newObj.getClass().getMethod(methodName, parameterTypes);
//                    Method methodGet = oldObj.getClass().getMethod(methodName.replace("set", "get"));
                    Method methodGet = oldObj.getClass().getMethod(convertMethodSetToGet(methodName));
                    methodSet.invoke(newObj, methodGet.invoke(oldObj));
                } catch (NoSuchMethodException e) {
                    //Logger.error(methodName + "to get is " + e.getMessage());
                } catch (Exception e) {
//                    Logger.error("clone exception", e);
                }
            }
        }
    }

    private static String convertMethodSetToGet(String methodName) {
        if (StringUtils.isEmpty(methodName)) {
            return methodName;
        }
        int index = methodName.indexOf("set");
        if (index != 0) {
            return methodName;
        }
        return "get" + methodName.substring(index + 3);
    }


    public static List<BizObject> decodeBills(BillContext billContext, Object obj) throws Exception {
        List<BizObject> bills = new ArrayList<BizObject>();
        // 前台传入JSON数据

        if (obj instanceof String) {
            String data = (String) obj;
            Json json = new Json(data);// JsonLoader.load("src/main/resources/json/sc_mall_Order.json");
            bills = Objectlizer.decode(json, billContext.getFullname());
        } else if (obj instanceof List) {
            bills = (List<BizObject>) obj;
        }

        return bills;
    }

    public static boolean isDuplicateByFullname(String fullname, String key, BizObject bill) {
        try {
            Entity entity = MetaDaoHelper.getEntity(fullname);
            PartitionContext contextData = AppContext.getPartitionContextData(entity, true);
            contextData.put("store", "*");
            UniqueCheckWalker uniqueCheckWalker = new UniqueCheckWalker(contextData);

            Property attribute = MetaUtils.findAttribute(fullname, key);
            BizObject billcopy = new BizObject();
            billcopy.init(bill);
            // if (BooleanUtils.b(attribute.isUnique())) {
            // if(EntityStatus.Unchanged==bill.getEntityStatus()){
            if (billcopy.getId() == null) {
                billcopy.setEntityStatus(EntityStatus.Insert);
            } else {
                billcopy.setEntityStatus(EntityStatus.Update);
            }
            // }
            return uniqueCheckWalker.uniqueCheck(entity, attribute, billcopy);
            // Object value=bill.get(attribute.name());
            // throw new BizException(attribute.name() + "_exist",
            // String.format("%s(%s)已经存在", attribute.title(),value));
            // }
        } catch (Exception e) {
            logger.error("isDuplicate", e);
            return true;
        }
    }

    // 查重
    /*
     * public static void isDuplicate(BillContext billContext, String field, String
     * value, String id,Long tenantId) throws Exception { Entity entity =
     * MetaDaoHelper.getEntity(billContext.getFullname()); isDuplicate(entity,
     * field, value, id, billContext.getDefWhere(),tenantId); }
     */
    public static boolean isDuplicate(BillContext billContext, String key, BizObject bill) {
        return isDuplicateByFullname(billContext.getFullname(), key, bill);
    }


    // 检查停用
    public static RuleExecuteResult checkStop(BizObject bill, Date vouchtime, String fullname, String key, String value)
            throws Exception {
        RuleExecuteResult result = new RuleExecuteResult();

        if (null != vouchtime) {
            if (key.lastIndexOf('.') > 0) {
                key = key.substring(0, key.lastIndexOf("."));
            }
            String itemFullname = MetaDaoHelper.getSubAttrFullname(fullname, key);
            List<Map<String, Object>> list = MetaDaoHelper.queryById(itemFullname, "stoptime", Long.valueOf(value));
            if (null != list && list.size() > 0 && null != list.get(0)) {
                Date stoptime = (Date) list.get(0).get("stoptime");

                if (vouchtime.getTime() > stoptime.getTime()) {

                    result.setMsgCode(0);
                    result.setMessage(com.yonyou.ucf.mdd.ext.i18n.utils.MddMultilingualUtil
                            .getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065213", "未启用") /* "未启用" */);
                    return result;
                }

            }
        }
        return result;
    }

    public static void appendCondition(BillDataDto billData, String field, String op, Object value) {
        FilterVO filterVO = billData.getCondition();
        filterVO = (FilterVO) UiMetaDaoHelper.appendCondition(filterVO, field, op, value);
        billData.setCondition(filterVO);
    }

    public static void appendTreeCondition(BillDataDto billData, String field, String op, Object value) {
        FilterVO filterVO = billData.getTreeCondition();
        filterVO = (FilterVO) UiMetaDaoHelper.appendCondition(filterVO, field, op, value);
        billData.setTreeCondition(filterVO);
    }

    public static void addLastOrg(BillContext billContext, BizObject bill) throws Exception {
        if (null == bill) {
            return;
        }
        // 获取交易类型的key信息
        addTransTypeKeyField(billContext, bill);
        String masterOrgField = MetaAttributeUtils.getFieldByAttributeOrName(billContext.getFullname(), "isMasterOrg",
                "org");
        bill.put("masterOrgKeyField", masterOrgField);
        if (Toolkit.isEmpty(masterOrgField)) {
            return;
        }
        if (!Toolkit.isEmpty(bill.get(masterOrgField))) {
            return;
        }
        Property attribute = MetaUtils.findAttribute(billContext.getFullname(), masterOrgField);
        boolean isDataControl = false;
        if (null != attribute) {
            isDataControl = BooleanUtils.b(attribute.get("isDataControl"));
        }
        String org;
        Object defaultOrg = BillMasterOrgService.getDefaultOrg(billContext.getBillnum());
        if (null != defaultOrg) {
            org = defaultOrg.toString();
        } else {
            org = BillMasterOrgService.getLastOrg(billContext.getBillnum(), isDataControl);
        }
        if (null != org) {
            bill.set(masterOrgField, org);
            Map<String, Object> funcOrg = getFunOrgById(org);
            if (funcOrg != null) {
                bill.set("masterorg_auto", funcOrg);
            }
        }
    }

    /**
     * 通过租户ID获取组织信息
     *
     * @param org
     * @return
     * @throws
     */
    public static Map<String, Object> getFunOrgById(String org) throws BaseDocException {
        funcOrgDataQryService = getFuncOrgDataQryService();
        if (funcOrgDataQryService != null) {
            FuncOrg funcOrg = funcOrgDataQryService.getById(org, AppContext.getYhtTenantId(), "diwork", "adminorg");
            if (funcOrg == null) {
                return null;
            }
            OrgUnit orgUnit = JSONObject.parseObject(funcOrg.toString(), OrgUnit.class);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("id", funcOrg.getId());
            resultMap.put("code", orgUnit.getCode());
            if (orgUnit.getName() != null) {
                MultiLangText multiLangText = orgUnit.getName();
                String code = MddConstants.LANGCODE_SIMPLE_CHINESS;
                LanguageVO languageVO = AppContext.getCurrentUser().getDefaultMulti();
                if (languageVO != null) {
                    code = languageVO.getLangCode();
                }
                String name = multiLangText.getText(code);
                resultMap.put("name", name);
            }
            return resultMap;
        }
        return null;
    }

    /**
     * 是否单组织
     * 先从上下文取，兼容老代码如果上下文没有则强制从参数里取一次
     *
     * @return
     */
    public static Boolean isSingleOrg() {
        if (AppContext.isShopUser()) {
            return true;
        }
        Boolean value = AppContext.getCurrentUser().getIsSingleOrg();
        if (value == null) {
            try {
                AbstractSystemCacheUtil op = OptionValueRpcCacheUtil.getInstance();
                String key = OptionValueRpcCacheUtil.PREFIX_FORMAT_STRING + "singleOrg" + AppContext.getTenantId() + AppContext.getUserId();
                value = op.get(key);
                if (value == null) {
                    Object isSingleOrgObj = OptionUtils.getSysOptionByName("singleOrg");
                    value = BooleanUtils.b(isSingleOrgObj);
                    op.put(key, value);
                }
            } catch (Exception e) {
                logger.error("获取当前环境异常", e);
                value = false;
            }
           /* if (value != null) {
                LoginUser loginUser = AppContext.getCurrentUser();
                //loginUser.setIsSingleOrg(value);
                AppContext.setCurrentUser(loginUser);
            }*/
        }
        return value;
    }

    public static <T extends BizObject> T add(BillContext billContext, String fullname, List<T> bills)
            throws Exception {
        return add(billContext, fullname, bills, false);
    }

    public static <T extends BizObject> T add(BillContext billContext, String fullname, List<T> bills, boolean isCopy) throws Exception {
        T bill;
        if (bills.size() == 0) {
            bill = MetaDaoHelper.add(fullname);
            bills.add(bill);
        } else {
            bill = bills.get(0);
        }
        return add(billContext, fullname, bill, isCopy);
    }

    private static <T extends BizObject> T add(BillContext billContext, String fullname, T bill, boolean isCopy) throws Exception {
        Entity entity = StringUtils.isBlank(fullname) ? null : IMetaUtils.entity(fullname);
        bill.setMetaInfo(entity);
        // 创建人、创建时间
        setAddAuditInfo(bill);
        // 单据日期
        setAddVouchDateInfo(bill, entity);
        clear(entity, bill);
        // TenantId
        setTenant(billContext, bill);
        if (!isCopy) {
            addLastOrg(billContext, bill);
        }

        // 取单据号
        String billcode = null;
        Map<String, String> billCodeMap = new HashMap<>();
        if (isAutoCode(fullname)) {
            long l = System.currentTimeMillis();
            IBillCodeComponentService billCodeService = AppContext.getBean(IBillCodeComponentService.class);
            billCodeMap = billCodeService.getBatchBillNumber(billContext.getBillnum(),billContext.getFullname(),bill,Boolean.FALSE);
            logger.info("getBatchBillNumber:{}", System.currentTimeMillis() - l);
        }
        if (null != bill && null != billCodeMap) {
            bill.putAll(billCodeMap);
        }
        return bill;
    }

    // 拷贝清空子对象属性
    public static BizObject copyClear(String fullname, BizObject bill) throws Exception {
        if (null == bill)
            return null;
        Entity entity = BizContext.getMetaRepository().entity(fullname);
        if (entity.is(BizContext.getMetaRepository().itf("base.itf.IPrintCount"))) {// 打印次数清空
            bill.set("printCount", null);
        }
        Map<String, BizObject> data = new HashMap<>();
        data.put("bill", bill);
        EntityWalker.walk(new ChainWalker<Association, Object>() {

            private void walk2(Association asso, Map<String, Object> data) {
                String subFullname = asso.typeA().fullname();
                String childFieldName = asso.roleA().name();

                BizObject parentData = (BizObject) data.get(asso.typeB().fullname());
                if (null == parentData) {
                    parentData = bill;
                }
                Object subData = parentData.get(childFieldName);

                if (subData == null) {
                    List<BizObject> lst = new ArrayList<BizObject>();
                    parentData.put(childFieldName, lst);
                    BizObject child = BizContext.getObject(subFullname);
                    Entity subEntity = BizContext.getMetaRepository().entity(subFullname);
                    if (child == null && subEntity != null) {
                        // 如果child为空，subEntity不为空，则需要直接用新的 BizObject对象
                        child = new BizObject();
                    }
                    if (null != child) {
                        child.setId(null);
                        if (null != subEntity) {
                            Property keyProperty = entity.keyAttribute();
                            if (null != keyProperty) {
                                child.set(keyProperty.name(), null);
                            }
                            Property syncProperty = entity.syncAttribute();
                            if (null != syncProperty) {
                                child.set(syncProperty.name(), null);
                            }
                        } else {
                            child.setId(null);
                            child.set("id", null);
                            child.setPubts(null);
                        }

                        lst.add(child);
                        data.put(subFullname, child);
                    }
                }
            }

            @Override
            public void walk(Association asso, Object obj) {
                walk2(asso, (Map<String, Object>) obj);
            }
        }, data, fullname);
        return bill;
    }

    public static boolean isAutoCode(String fullname) {
        Entity entity = BizContext.getMetaRepository().entity(fullname);
        return isAutoCode(entity);
    }

    public static boolean isAutoCode(Entity entity) {
        boolean isCode = false;
        isCode = entity.is(BizContext.getMetaRepository().itf("voucher.base.IAutoCode"));
        if (isCode) {
            try {
                Property attribute = MetaUtils.findAttribute(entity.fullname(), "code");
                if (null != attribute) {
                    isCode = attribute.isCode();
                }
            } catch (Exception e) {
                logger.error("isAutoCode exception", e);
            }
        }
        return isCode || isAutoCodeExtend(entity); // 兼容 的自动编码配置逻辑
    }

    public static boolean isAutoCodeExtend(Entity entity) {
        String itfFullName = null;
        try {
            ResourceBundle applic = ResourceBundle.getBundle("application");
            if (applic != null) {
                itfFullName = applic.getString(MddConstants.CONFIG_AUTO_CODE_ITF);
            }
        } catch (Exception e) {
            String message = String.format("获取fullName:%s的配置信息：%s异常,异常信息:%s", entity.fullname(),
                    MddConstants.CONFIG_AUTO_CODE_ITF, e.getMessage());
            logger.error(message);
        }
        if (itfFullName == null) {
            itfFullName = "ucfbase.ucfbaseItf.IAutoCode";
        }
        return IMetaUtils.isImplementOf(entity, itfFullName);
    }

    public static Set<String> getOrgPermissions(String billnum) throws Exception {
        String authId = OrgPermissionUtils.getAuth(billnum);
        if (null == authId)
            return null;

        return getOrgPermissionsByAuth(authId);
    }

    public static Set<String> getOrgPermissions(String billnum, Boolean includeDisable) throws Exception {

        String serviceCode = AppContext.getThreadContext(MddConstants.PARAM_SERVICE_CODE);
        if (StringUtils.isEmpty(serviceCode)) {
            serviceCode = OrgPermissionUtils.getAuth(billnum);
        }
        if (null == serviceCode)
            return null;


        return getOrgPermissionsByAuth(serviceCode, includeDisable);
    }

    /**
     * 获取带有交易类型单据的主组织数据
     *
     * @param billNo    单据编码
     * @param transType 交易类型
     * @return
     * @throws Exception
     */
    public static Set<String> getOrgPermissionsWithTransType(String billNo, String transType) throws Exception {
        String authId = OrgPermissionUtils.getAuth(billNo);
        if (null == authId) {
            return null;
        }
        if (StringUtils.isNotEmpty(transType)) {
            authId = ExtAuthUtils.getTransTypeAuthId(transType, authId);
        }
        return getOrgPermissionsByAuth(authId);
    }

    public static Set<String> getOrgPermissionsByAuth(String authId) throws Exception {
        if (isSingleOrg()) {
            LoginUser user = AppContext.getCurrentUser();
            if (null != user) {
                String org = user.get(Constants.SINGLEORGID);
                if (!Toolkit.isEmpty(org)) {
                    Set<String> orgs = new HashSet<>(1);
                    orgs.add(org);
                    return orgs;
                }
            }
        }
        return OrgPermissionUtils.getOrgPermissionsByAuth(authId);
    }

    private static Set<String> getOrgPermissionsByAuth(String serviceCode, boolean includeDisable) throws Exception {
        if (isSingleOrg()) {
            LoginUser user = AppContext.getCurrentUser();
            if (null != user) {
                String org = user.get(Constants.SINGLEORGID);
                if (!Toolkit.isEmpty(org)) {
                    Set<String> orgs = new HashSet<>(1);
                    orgs.add(org);
                    return orgs;
                }
            }
        }
        /*IOrgPermissionService orgPermissionService = DubboReferenceUtils.getDubboService(IOrgPermissionService.class, Constants.AUTHDOMAIN, null);
        return orgPermissionService.getOrgPermissions(new OrgPermissionsParam(serviceCode, includeDisable));*/
        return MddAuthPermissionUtils.getMasterOrgPermissionByAuthId(serviceCode, includeDisable);
    }

    public static String getAuth(String billnum) throws Exception {
        return OrgPermissionUtils.getAuth(billnum);
    }

    public static Short getStatus(BizObject bill) {
        Short status = null;

        if (null != bill.get("status")) {
            status = Short.valueOf(bill.get("status").toString());
        }
        return status;
    }

    public static void updateLastStatus(String fullname, Long id) {
        try {
            Entity mainEntity = MetaDaoHelper.getEntity(fullname);
            LoginUser user = AppContext.getCurrentUser();
            Map<String, Object> params = new HashMap<>();

            params.put("tablename", mainEntity.tableName());
            params.put("id", id);
            params.put("tenant_id", user.getTenant());
            params.put(MddConstants.PARTITION_Y_TENANT_KEY, AppContext.getYTenantId());

            SqlHelper.insert("com.yonyou.ucf.mdd.ext.vouch.closestatus.insertOrUpdateCloseStatus", params);
        } catch (Exception e) {
            logger.error("updateLastStatus", e);
            throw new MddOrmErrorException(e.getMessage(), e);
        }
    }

    public static void setLastCloseStatus(BizObject bill, String fullname) {
        Short status = null;

        try {
            Entity mainEntity = MetaDaoHelper.getEntity(fullname);
            LoginUser user = AppContext.getCurrentUser();
            Map<String, Object> params = new HashMap<>();

            params.put("tablename", mainEntity.tableName());
            params.put("id", bill.getId());
            params.put("tenant_id", user.getTenant());

            status = SqlHelper.selectFirst("com.yonyou.ucf.mdd.ext.vouch.closestatus.getLastCloseStatus", params);
        } catch (Exception e) {
            logger.error("updateLastStatus", e);
        }
        if (null != status) {
            bill.set("status", status);
        }
    }

    public static Date getBusinessDate() {
        Date businessDate = null;
        LoginUser user = AppContext.getCurrentUser();
        if (null != user) {
            if (null != user.getBusinessDate()) {
                businessDate = user.getBusinessDate();
            }
        }
        if (null == businessDate) {
            businessDate = DateKit.getNowDate();
        }
        businessDate.setHours(0);
        businessDate.setMinutes(0);
        businessDate.setSeconds(0);
        return businessDate;
    }

    /**
     * 添加交易类型key信息
     *
     * @param billContext 实体fullName
     * @param bill        业务数据
     */
    public static void addTransTypeKeyField(BillContext billContext, Map bill) {
        if (billContext == null || bill == null) {
            return;
        }
        try {
            String transactionTypeField = MetaAttributeUtils.getFieldByAttributeOrName(billContext.getFullname(), "isTransactionType", "bustype");
            bill.put("transTypeKeyField", transactionTypeField);
        } catch (Exception e) {
            logger.error(">>>#addTransTypeKeyField#添加交易类型key属性异常!", e);
        }
    }


    /**
     * 是否是卡片
     *
     * @param billContext
     * @return
     */
    public static boolean isCard(BillContext billContext) {
        if ((billContext.getBillnum() != null && billContext.getBillnum().equalsIgnoreCase(billContext.getCardKey())) || org.apache.commons.lang3.StringUtils.isEmpty(billContext.getCardKey())) {
            return true;
        }
        return false;
    }

        public static Long getTplId(String billNo, String transTypeId, String orgId, String serviceCode, String terminalType) {
        // 获取tplId信息
        MddBillTplQueryService mddBillTplQueryService = AppContext.getBean(MddBillTplQueryService.class);
        if (mddBillTplQueryService != null) {
            TplQueryParam tplQueryParam = new TplQueryParam();
            // 获取业务数据中的
            String yhtUserId = AppContext.getCurrentUser() == null ? null : AppContext.getCurrentUser().getYhtUserId();
            String dbTenantId = MdfMapKeyUtil.getStringValue(AppContext.getTenantId());
            String yhtTenantId =
                    AppContext.getCurrentUser() == null ? null : AppContext.getCurrentUser().getYhtTenantId();
            tplQueryParam.setBillNo(billNo);
            tplQueryParam.setTransTypeId(transTypeId);
            tplQueryParam.setOrgId(orgId);
            tplQueryParam.setServiceCode(serviceCode);
            tplQueryParam.setUserId(yhtUserId);
            tplQueryParam.setDbTenantId(dbTenantId);
            tplQueryParam.setYhtTenantId(yhtTenantId);
            tplQueryParam.setTerminalType(terminalType);
            View view = mddBillTplQueryService.getSingleTpl(tplQueryParam);
            if (view != null && view.getTplId() != null) {
                return MdfMapKeyUtil.getLongValue(view.getTplId());
            }
        }
        return null;
    }

}
